package com.shuaiche.yeguan.ui.map;

import android.Manifest;
import android.app.Dialog;
import android.content.pm.PackageManager;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.MapView;
import com.amap.api.maps.MapsInitializer;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.CameraPosition;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.MyLocationStyle;
import com.amap.api.services.core.AMapException;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.core.ServiceSettings;
import com.amap.api.services.geocoder.GeocodeResult;
import com.amap.api.services.geocoder.GeocodeSearch;
import com.amap.api.services.geocoder.RegeocodeAddress;
import com.amap.api.services.geocoder.RegeocodeQuery;
import com.amap.api.services.geocoder.RegeocodeResult;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.shuaiche.yeguan.R;
import com.shuaiche.yeguan.SCApplication;
import com.shuaiche.yeguan.model.ChangeLocation;
import com.shuaiche.yeguan.model.SCAddressParamsModel;
import com.shuaiche.yeguan.util.LogUtils;
import com.shuaiche.yeguan.util.StringUtils;
import com.shuaiche.yeguan.util.ToastShowUtils;
import com.shuaiche.yeguan.util.permission.MPermission;
import com.shuaiche.yeguan.util.permission.OnMPermissionDenied;
import com.shuaiche.yeguan.util.permission.OnMPermissionGranted;
import com.shuaiche.yeguan.util.permission.OnMPermissionNeverAskAgain;

import java.util.ArrayList;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;

public class LocationMapActivity extends AppCompatActivity implements AMapLocationListener, AMap.OnMapLoadedListener, AMap.OnCameraChangeListener, GeocodeSearch.OnGeocodeSearchListener, View.OnClickListener{

    private static final int BASIC_PERMISSION_REQUEST_CODE_FOR_LOCATION = 1002;  //定位权限

    MapView mapView;
    ImageButton ibLocation;
    RelativeLayout rlMap;

    private AMap aMap;
    private MyLocationStyle myLocationStyle;
    private AMapLocationClient aMapLocationClient = null;
    private AMapLocationClientOption mLocationOption = null;
    private AMapLocationListener aMapLocationListener;

    // 定位的经纬度
    private LatLng locationLatLng;
    // 地图移动过后的经纬度
    private LatLng target;
    private GeocodeSearch geocodeSearch;
    private Marker mPositionMark;

    // 逆编码地理 地址信息
    private SCAddressParamsModel addressParams;
    private RegeocodeAddress regeocodeAddress;
    private RegeocodeQuery regeocodeQuery;


    // 城市编码
    private String cityCode;
    private String city;
    private double latitude;
    private double longitude;
    private String locationDistrict;
    private String locationProvince;
    private String locationCity;
    private String locationAddress;
    private ArrayList<ChangeLocation> nearByList;
    private ArrayList<ChangeLocation> inputList;

    // 需要传递回去的location
    private ChangeLocation mTransferLocation = new ChangeLocation();

    private Double lat;
    private Double lon;
    private LatLng latLng;
    private boolean hasLocation;

    private RelativeLayout rl_back;
    private TextView tv_confirm;

    private Double resultLat;
    private Double resultLon;

    private boolean isFirstOnCameraChange = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
        setContentView(R.layout.activity_location_map);

        getData();
        initViews();
        mapView.onCreate(savedInstanceState);
    }

    private void initViews() {
        initFindviews();

        MapsInitializer.updatePrivacyShow(this,true,true);
        MapsInitializer.updatePrivacyAgree(this,true);
        ServiceSettings.updatePrivacyShow(this,true,true);
        ServiceSettings.updatePrivacyAgree(this,true);

        initMapview();

    }

    private void getData() {
        if (getIntent() != null) {
            lat = getIntent().getDoubleExtra("lat",0f);
            lon = getIntent().getDoubleExtra("lon",0f);

            cityCode = getIntent().getStringExtra("cityCode");
            hasLocation = getIntent().getBooleanExtra("hasLocation", false);
            if (lat != 0f && lon != 0f) {
                latLng = new LatLng(lat, lon);
                latitude = lat;
                longitude = lon;
            }
        }
    }

    private void initMapview() {
        if (Build.VERSION.SDK_INT >= 23) {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

                showCustomDialog();

            }else {

                initMap();
            }
        }
    }

    private void showCustomDialog() {
        Dialog dialog = new Dialog(this);
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        dialog.setContentView(R.layout.dialog_permission);

        dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        dialog.setCancelable(false);
        Button btnApply = dialog.findViewById(R.id.btn_apply);
        Button btnReject = dialog.findViewById(R.id.btn_reject);

        btnApply.setOnClickListener(v -> {
            MPermission.with(LocationMapActivity.this)
                    .setRequestCode(BASIC_PERMISSION_REQUEST_CODE_FOR_LOCATION)
                    .permissions(Manifest.permission.ACCESS_FINE_LOCATION,
                            Manifest.permission.ACCESS_COARSE_LOCATION)
                    .request();
            // 申请定位权限
            dialog.dismiss();
        });

        btnReject.setOnClickListener(v -> {
            dialog.dismiss();
        });

        dialog.show();
    }
    @OnMPermissionGranted(BASIC_PERMISSION_REQUEST_CODE_FOR_LOCATION)
    public void onBasicPermissionSuccess() {
        initMap();
    }

    @OnMPermissionDenied(BASIC_PERMISSION_REQUEST_CODE_FOR_LOCATION)
    @OnMPermissionNeverAskAgain(BASIC_PERMISSION_REQUEST_CODE_FOR_LOCATION)
    public void onBasicPermissionFailed() {
        ToastShowUtils.showTipToast("请先赋予app定位权限");
    }

    private void initFindviews() {
        mapView = findViewById(R.id.map_view);
        ibLocation = findViewById(R.id.ib_location);
        rlMap = findViewById(R.id.rl_map);

        rl_back = findViewById(R.id.rl_back);
        tv_confirm = findViewById(R.id.tv_confirm);

        ibLocation.setOnClickListener(this);
        rl_back.setOnClickListener(this);
        tv_confirm.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.ib_location:
                reLocation();
                break;
            case R.id.rl_back:
                finish();
                break;
            case R.id.tv_confirm:
                postAddress(mTransferLocation);
                break;
        }
    }

    /**
     * 定位icon的点击事件
     */
    private void reLocation() {
        if (aMap != null && locationLatLng != null) {
            aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(locationLatLng, 18));


            resultLat = locationLatLng.latitude;
            resultLon = locationLatLng.longitude;
        }
    }

    private void initMap() {
        if (aMap == null) {
            aMap = mapView.getMap();
        }
        initLocationStyle();
        initLocationListener();
        aMap.setOnMapLoadedListener(this);
        aMap.setOnCameraChangeListener(this);

    }

    private void initLocationStyle() {
        //初始化定位蓝点样式类
        myLocationStyle = new MyLocationStyle();
        //定位一次，且将视角移动到地图中心点。
        myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATE);
        //设置连续定位模式下的定位间隔，只在连续定位模式下生效，单次定位模式下不会生效。单位为毫秒。
//        myLocationStyle.interval(3000);
        //方法自5.1.0版本后支持
        //设置是否显示定位小蓝点，用于满足只想使用定位，不想使用定位小蓝点的场景，
        // 设置false以后图面上不再有定位蓝点的概念，但是会持续回调位置信息。
        myLocationStyle.showMyLocation(true);
        // 不显示蓝色的范围圆圈
        myLocationStyle.strokeColor(Color.argb(0, 0, 0, 0));// 设置圆形的边框颜色
        myLocationStyle.radiusFillColor(Color.argb(0, 0, 0, 0));// 设置圆形的填充颜色
        //设置定位蓝点的Style
        aMap.setMyLocationStyle(myLocationStyle);
        // 设置默认定位按钮是否显示，非必需设置。
        aMap.getUiSettings().setMyLocationButtonEnabled(false);
        aMap.getUiSettings().setZoomControlsEnabled(false);
        // 倾斜手势：是否可以双指倾斜
        aMap.getUiSettings().setTiltGesturesEnabled(false);
        // 设置为true表示启动显示定位蓝点，false表示隐藏定位蓝点并不进行定位，默认是false。
        aMap.setMyLocationEnabled(true);
    }

    private void initLocationListener() {
        try {
            aMapLocationClient = new AMapLocationClient(getApplicationContext());
            if (aMapLocationClient == null) {
                return;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        //初始化定位参数
        mLocationOption = new AMapLocationClientOption();
        //设置为高精度定位模式
        mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
        // 设置setOnceLocationLatest(boolean b)接口为true，启动定位时SDK会返回最近3s内精度最高的一次定位结果
        mLocationOption.setOnceLocation(true);
        // 且该结果一定来自与设备环境相符合的AP源
        mLocationOption.setOnceLocationLatest(true);
        //设置是否返回地址信息（默认返回地址信息）
        mLocationOption.setNeedAddress(true);
        //设置定位参数
        aMapLocationClient.setLocationOption(mLocationOption);
        //设置定位回调监听
        aMapLocationClient.setLocationListener(this);
        //启动定位
        aMapLocationClient.startLocation();
    }

    @Override
    public void onMapLoaded() {
        MarkerOptions markerOptions = new MarkerOptions();
        markerOptions.setFlat(true);
        markerOptions.anchor(0.5f, 0.5f);
        markerOptions.position(new LatLng(0, 0));
        markerOptions.icon(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.icon_map_marker)));
        mPositionMark = aMap.addMarker(markerOptions);

        if (latLng != null) {
            moveToLocationed();
        } else {
            if (locationLatLng != null) {
                aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(locationLatLng, 18));
            } else {
                aMap.moveCamera(CameraUpdateFactory.zoomTo(18));
            }
        }

        mPositionMark.showInfoWindow();
        //主动显示infoWindow 
        mPositionMark.setPositionByPixels(mapView.getWidth() / 2, rlMap.getHeight() / 2);
    }

    /**
     * 移动到指定地点
     */
    private void moveToLocationed() {
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                if (aMap != null && latLng != null) {
                    aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 18));
                }
            }
        }, 900);

    }

    @Override
    public void onCameraChange(CameraPosition cameraPosition) {
        //这个target 就是地图移动过后中心点的经纬度
        target = cameraPosition.target;
        //这个方法是逆地理编码解析出详细位置
//        Geo(target);
//        LogUtils.log("onCameraChange",cameraPosition.target.toString());
    }

    @Override
    public void onCameraChangeFinish(CameraPosition cameraPosition) {
        if (isFirstOnCameraChange){
            isFirstOnCameraChange = false;
        }

        latitude = cameraPosition.target.latitude;
        longitude = cameraPosition.target.longitude;

        if (!isFirstOnCameraChange){
            resultLat = latitude;
            resultLon = longitude;
        }

//        Geo(cameraPosition.target);
        LogUtils.log("onCameraChangeFinish",cameraPosition.target.toString());
    }

    /**
     * 先要执行逆地理编码的搜索
     *
     * @param latlng 逆地理编码
     */
    public void Geo(LatLng latlng) {
        try {
            geocodeSearch = new GeocodeSearch(this);
        } catch (AMapException e) {
            e.printStackTrace();
        }
        geocodeSearch.setOnGeocodeSearchListener(this);
        //和上面一样
        // 第一个参数表示一个Latlng(经纬度)，第二参数表示范围多少米，第三个参数表示是火系坐标系还是GPS原生坐标系
        RegeocodeQuery query = new RegeocodeQuery(new LatLonPoint(latlng.latitude, latlng.longitude), 200, GeocodeSearch.AMAP);
        geocodeSearch.getFromLocationAsyn(query);

    }

    private void recordLocation() {
        mTransferLocation.setAddress(regeocodeAddress.getFormatAddress());
        mTransferLocation.setLatitude(regeocodeQuery.getPoint().getLatitude());
        mTransferLocation.setLongitude(regeocodeQuery.getPoint().getLongitude());

        mTransferLocation.setProvince(regeocodeAddress.getProvince());
        mTransferLocation.setCity(regeocodeAddress.getCity());
        mTransferLocation.setDistrict(regeocodeAddress.getDistrict());
        mTransferLocation.setAdCode(regeocodeAddress.getAdCode());
        mTransferLocation.setCityCode(regeocodeAddress.getCityCode());
    }

    @Override
    public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int i) {
        // 如果逆地理编码成功，就获取到中心点的详细位置，并且在TextView中进行显示，就如同一开始的那张图片所示。
        if (i == AMapException.CODE_AMAP_SUCCESS) {
            LogUtils.log("onRegeocodeSearched","CODE_AMAP_SUCCESS");
            if (regeocodeResult != null) {
                regeocodeAddress = regeocodeResult.getRegeocodeAddress();
                regeocodeQuery = regeocodeResult.getRegeocodeQuery();
                cityCode = regeocodeAddress.getCityCode();
                city = regeocodeAddress.getCity();

                recordLocation();
            }
        } else {
            LogUtils.log("onRegeocodeSearched", "onRegeocodeSearched Error:" + i);
        }
    }

    @Override
    public void onGeocodeSearched(GeocodeResult geocodeResult, int i) {

    }

    @Override
    public void onLocationChanged(AMapLocation aMapLocation) {

        if (aMapLocation != null) {
            LogUtils.log("onLocationChanged",aMapLocation.toString());
            if (aMapLocation.getErrorCode() == 0) {
                //可在其中解析amapLocation获取相应内容。
                locationLatLng = new LatLng(aMapLocation.getLatitude(), aMapLocation.getLongitude());

                if (latLng == null){
                    resultLat = aMapLocation.getLatitude();
                    resultLon =  aMapLocation.getLongitude();
                }

                cityCode = aMapLocation.getCityCode();
                city = aMapLocation.getCity();
//                latitude = aMapLocation.getLatitude();
//                longitude = aMapLocation.getLongitude();
                locationDistrict = aMapLocation.getDistrict();
                locationProvince = aMapLocation.getProvince();
                locationCity = aMapLocation.getCity();
//                locationAddress = aMapLocation.getAddress();
                locationAddress = aMapLocation.getPoiName();

                if (latLng != null) {
                    moveToLocationed();
                }
            } else {
                //定位失败时，可通过ErrCode（错误码）信息来确定失败的原因，errInfo是错误信息，详见错误码表。
                LogUtils.log("onLocationChanged", "location Error, ErrCode:"
                        + aMapLocation.getErrorCode() + ", errInfo:"
                        + aMapLocation.getErrorInfo());
            }
        }
    }

    private void postAddress(ChangeLocation location) {
//        if (StringUtils.isEmpty(location.getAddress())) {
//            ToastShowUtils.showTipToast("地址不能为空");
//        } else {
        addressParams = new SCAddressParamsModel();
//        addressParams.setLocationAddTitle(location.getName());
//        if (!StringUtils.isEmpty(location.getAddress())) {
//            addressParams.setDetailAddress(location.getAddress());
//        } else {
//            addressParams.setDetailAddress(location.getDistrict() + location.getName());
//        }
//        addressParams.setLatitude(location.getLatitude());
//        addressParams.setLongitude(location.getLongitude());
//
//        addressParams.setProvince(location.getProvince());
//        addressParams.setCity(location.getCity());
//        addressParams.setAdName(location.getAdName());
//        addressParams.setDistrict(location.getDistrict());
//
//        addressParams.setAdCode(location.getAdCode());
//        addressParams.setCityCode(location.getCityCode());
        goBackPrevious();
//        }
    }

    private void goBackPrevious() {
//        Intent intent = new Intent();
//        intent.putExtra("address", addressParams);
//        setResult(Activity.RESULT_OK, intent);
//        finish();

        ReactContext reactContext = SCApplication.getApplication().getReactNativeHost().getReactInstanceManager().getCurrentReactContext();
        if (reactContext == null) {
            return;
        }
        WritableMap event = Arguments.createMap();
        //传递的参数
        event.putString("address", "");
        event.putDouble("lat", resultLat);
        event.putDouble("lon", resultLon);
        reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("selectMapResult",event);

        finish();
    }



    @Override
    public void onPointerCaptureChanged(boolean hasCapture) {
        super.onPointerCaptureChanged(hasCapture);
    }


    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mapView.onSaveInstanceState(outState);
    }

    @Override
    public void onResume() {
        super.onResume();
        mapView.onResume();
    }

    @Override
    public void onPause() {
        super.onPause();
        mapView.onPause();
    }

    @Override
    public void onStop() {
        super.onStop();
        if (aMapLocationClient != null) {
            aMapLocationClient.stopLocation();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (aMapLocationClient != null) {
            aMapLocationClient.onDestroy();
        }
        if (aMap != null) {
            aMap.setMyLocationEnabled(false);
        }
        if (mapView != null) {
            mapView.onDestroy();
        }
        aMap = null;
    }
}